home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2001 May / may_2001.iso / intercd / root / Multimedia / ^DivX_Article / virtualdub / VirtualDub-source-1_4d / LevelControl.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-20  |  8.7 KB  |  359 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Copyright (C) 1998-2001 Avery Lee
  3. //
  4. //    This program is free software; you can redistribute it and/or modify
  5. //    it under the terms of the GNU General Public License as published by
  6. //    the Free Software Foundation; either version 2 of the License, or
  7. //    (at your option) any later version.
  8. //
  9. //    This program is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. //    GNU General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU General Public License
  15. //    along with this program; if not, write to the Free Software
  16. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #define f_POSITIONCONTROL_CPP
  19.  
  20. #include <crtdbg.h>
  21. #include <math.h>
  22.  
  23. #include <windows.h>
  24. #include <commctrl.h>
  25.  
  26. #include "resource.h"
  27. #include "oshelper.h"
  28.  
  29. #include "LevelControl.h"
  30.  
  31. extern HINSTANCE g_hInst;
  32.  
  33. static LRESULT APIENTRY LevelControlWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
  34.  
  35. ////////////////////////////
  36.  
  37. extern const char g_szLevelControlName[]="birdyLevelControl";
  38.  
  39. #define        MAX_TABS        (8)
  40.  
  41. ////////////////////////////
  42.  
  43. typedef struct LevelControlData {
  44.     int            iPos[MAX_TABS];
  45.     int            iPixPos[MAX_TABS];
  46.     COLORREF    rgbTab[MAX_TABS];
  47.     int            nTabs;
  48.     int            iMovingTab;
  49.     int            iMovingOffset;
  50.     int            iTabW, iTabH;
  51.     RECT        rColorBand;
  52.     RECT        rTabBand;
  53.     COLORREF    rgbLow, rgbHigh;
  54.     int            w;
  55. } LevelControlData;
  56.  
  57. ////////////////////////////
  58.  
  59. ATOM RegisterLevelControl() {
  60.     WNDCLASS wc;
  61.  
  62.     wc.style        = 0;
  63.     wc.lpfnWndProc    = LevelControlWndProc;
  64.     wc.cbClsExtra    = 0;
  65.     wc.cbWndExtra    = sizeof(LevelControlData *);
  66.     wc.hInstance    = g_hInst;
  67.     wc.hIcon        = NULL;
  68.     wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
  69.     wc.hbrBackground= (HBRUSH)(COLOR_3DFACE+1);    //GetStockObject(LTGRAY_BRUSH);
  70.     wc.lpszMenuName    = NULL;
  71.     wc.lpszClassName= VIDEOLEVELCONTROLCLASS;
  72.  
  73.     return RegisterClass(&wc);
  74. }
  75.  
  76. static void LevelControlResize(HWND hwnd, LevelControlData *const lcd) {
  77.     RECT r;
  78.  
  79.     GetClientRect(hwnd, &r);
  80.  
  81.     lcd->iTabH        = r.bottom/2;
  82.     lcd->iTabW        = (lcd->iTabH*6+8)/16;
  83.  
  84.     lcd->rColorBand.left    = r.left+lcd->iTabW;
  85.     lcd->rColorBand.right    = r.right-lcd->iTabW;
  86.     lcd->rColorBand.top        = r.top;
  87.     lcd->rColorBand.bottom    = r.top+lcd->iTabH-1;
  88.  
  89.     lcd->rTabBand.left        = r.left;
  90.     lcd->rTabBand.right        = r.right;
  91.     lcd->rTabBand.top        = lcd->rColorBand.bottom;
  92.     lcd->rTabBand.bottom    = r.bottom;
  93.  
  94.     lcd->w                    = lcd->rColorBand.right - lcd->rColorBand.left;
  95. }
  96.  
  97. static int LevelRatioToPixel(int rat, int w) {
  98.     return (w * rat) >> 16;
  99. }
  100.  
  101. static int LevelPixelToRatio(int pix, int w) {
  102.     return (pix * 65535) / (w-1);
  103. }
  104.  
  105. static LRESULT APIENTRY LevelControlWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
  106.     LevelControlData *lcd = (LevelControlData *)GetWindowLong(hwnd, 0);
  107.  
  108.     switch(msg) {
  109.  
  110.     case WM_NCCREATE:
  111.         if (!(lcd = new LevelControlData))
  112.             return FALSE;
  113.         memset(lcd,0,sizeof(LevelControlData));
  114.  
  115.         lcd->nTabs        = 3;
  116.         lcd->iPos[0]    = 0;
  117.         lcd->rgbTab[0]    = 0xFFFFFF;
  118.         lcd->rgbLow        = 0x000000;
  119.         lcd->rgbHigh    = 0xFFFFFF;
  120.         lcd->iMovingTab    = -1;
  121.  
  122.         SetWindowLong(hwnd, 0, (LONG)lcd);
  123.         return TRUE;
  124.  
  125.     case WM_CREATE:
  126.     case WM_SIZE:
  127.         LevelControlResize(hwnd, lcd);
  128.         break;
  129.  
  130.     case WM_DESTROY:
  131.         delete lcd;
  132.         SetWindowLong(hwnd, 0, 0);
  133.         break;
  134.  
  135.     case WM_PAINT:
  136.         {
  137.             PAINTSTRUCT ps;
  138.             HDC hdc;
  139.             int i, x, w, h;
  140.             RECT r;
  141.  
  142.             hdc = BeginPaint(hwnd, &ps);
  143.  
  144.             w = lcd->w;
  145.             h = lcd->rColorBand.bottom - lcd->rColorBand.top;
  146.  
  147.             if (RectVisible(hdc, &lcd->rColorBand)) {
  148.                 int dr, dg, db;
  149.                 int xlo, xhi;
  150.                 RECT rClip;
  151.  
  152.                 dr = (signed long)(lcd->rgbHigh&0xff) - (signed long)(lcd->rgbLow&0xff);
  153.                 dg = ((signed long)(lcd->rgbHigh&0xff00) - (signed long)(lcd->rgbLow&0xff00))>>8;
  154.                 db = ((signed long)(lcd->rgbHigh&0xff0000) - (signed long)(lcd->rgbLow&0xff0000))>>16;
  155.  
  156.                 r = lcd->rColorBand;
  157.                 xlo = 0;
  158.                 xhi = w;
  159.  
  160.                 i = GetClipBox(hdc, &rClip);
  161.  
  162.                 if (i!=ERROR && i!=NULLREGION) {
  163.                     RECT rClip2;
  164.  
  165.                     IntersectRect(&rClip2, &r, &rClip);
  166.  
  167.                     xlo = rClip2.left - r.left;
  168.                     xhi = rClip2.right - r.left;
  169.                 }
  170.  
  171.                 for(x=xlo; x<xhi; x++) {
  172.                     HBRUSH hbr;
  173.                     COLORREF cr;
  174.  
  175.                     r.left = lcd->rColorBand.left + x;
  176.                     r.right = r.left+1;
  177.  
  178.                     cr    = lcd->rgbLow
  179.                         +  ((dr*x + w/2)/w)
  180.                         + (((dg*x + w/2)/w) << 8)
  181.                         + (((db*x + w/2)/w) << 16);
  182.  
  183.                     if (hbr = CreateSolidBrush(cr)) {
  184.                         FillRect(hdc, &r, hbr);
  185.                         DeleteObject(hbr);
  186.                     }
  187.                 }
  188.             }
  189.  
  190.             for(i=0; i<lcd->nTabs; i++) {
  191.                 POINT pt[3];
  192.                 HBRUSH hbr;
  193.                 HGDIOBJ hgoOld;
  194.  
  195.                 pt[0].x = lcd->iPixPos[i];
  196.                 pt[1].x = lcd->iPixPos[i]+lcd->iTabW;
  197.                 pt[2].x = lcd->iPixPos[i]+2*lcd->iTabW;
  198.                 pt[0].y = pt[2].y = lcd->rColorBand.bottom+lcd->iTabH-1;
  199.                 pt[1].y = lcd->rColorBand.bottom;
  200.  
  201.                 if (hbr = CreateSolidBrush(lcd->rgbTab[i]))
  202.                     hgoOld = SelectObject(hdc, hbr);
  203.  
  204.                 Polygon(hdc, pt, 3);
  205.  
  206.                 if (hbr)
  207.                     DeleteObject(SelectObject(hdc, hgoOld));
  208.             }
  209.  
  210.             EndPaint(hwnd, &ps);
  211.         }
  212.         break;
  213.  
  214.     case WM_LBUTTONDOWN:
  215.         {
  216.             int x = LOWORD(lParam);
  217.             int y = HIWORD(lParam);
  218.  
  219.             if (y >= lcd->rColorBand.bottom && y<lcd->rColorBand.bottom+lcd->iTabH) {
  220.                 int i;
  221.                 int best_tab = -1, best_dx = 100;
  222.  
  223.                 for(i=0; i<lcd->nTabs; i++) {
  224.                     int dx = (x-lcd->iTabW) - lcd->iPixPos[i];
  225.                     int adx = abs(dx);
  226.  
  227.                     // Pick the closest tab to cursor; if tabs are on the same
  228.                     // position, pick the lowest tab if mouse is to the left and
  229.                     // the highest tab if mouse is to the right
  230.  
  231.                     if (adx < 8 && (best_tab == -1 || adx < best_dx ||
  232.                         (adx == best_dx && dx>0))) {
  233.  
  234.                         best_dx = adx;
  235.                         best_tab = i;
  236.                     }
  237.  
  238.                 }
  239.                 if (best_tab >= 0) {
  240.                     SetCapture(hwnd);
  241.                     lcd->iMovingTab = best_tab;
  242.                     lcd->iMovingOffset = x - lcd->iPixPos[best_tab];
  243.                 }
  244.             }
  245.         }
  246.         break;
  247.  
  248.     case WM_LBUTTONUP:
  249.         if (lcd->iMovingTab>=0) {
  250.             ReleaseCapture();
  251.             lcd->iMovingTab = -1;
  252.         }
  253.         break;
  254.  
  255.     case WM_MOUSEMOVE:
  256.         if (lcd->iMovingTab>=0) {
  257.             int pos, pixpos;
  258.             RECT r;
  259.  
  260.             pixpos = (int)(signed short)LOWORD(lParam) - lcd->iMovingOffset;
  261.             pos = LevelPixelToRatio(pixpos, lcd->w);
  262.  
  263.             // clip position against spectrum
  264.  
  265.             if (pixpos<0) {
  266.                 pos = 0;
  267.                 pixpos = 0;
  268.             } else if (pixpos >= lcd->rColorBand.right - lcd->rColorBand.left) {
  269.                 pixpos = lcd->rColorBand.right - lcd->rColorBand.left - 1;
  270.                 pos = 0xFFFF;
  271.             }
  272.  
  273.             // don't let tabs pass each other
  274.  
  275.             if (lcd->iMovingTab>0 && pos < lcd->iPos[lcd->iMovingTab-1]) {
  276.                 pos = lcd->iPos[lcd->iMovingTab-1];
  277.                 pixpos = lcd->iPixPos[lcd->iMovingTab-1];
  278.             } else if (lcd->iMovingTab < lcd->nTabs-1 && pos > lcd->iPos[lcd->iMovingTab+1]) {
  279.                 pos = lcd->iPos[lcd->iMovingTab+1];
  280.                 pixpos = lcd->iPixPos[lcd->iMovingTab+1];
  281.             }
  282.  
  283.             // render changes
  284.  
  285.             r.left = lcd->iPixPos[lcd->iMovingTab];
  286.             r.right = lcd->iPixPos[lcd->iMovingTab]+2*lcd->iTabW+1;
  287.             r.top = lcd->rColorBand.bottom;
  288.             r.bottom = r.top + lcd->iTabH;
  289.  
  290.             InvalidateRect(hwnd, &r, TRUE);
  291.  
  292.             lcd->iPos[lcd->iMovingTab] = pos;
  293.             lcd->iPixPos[lcd->iMovingTab] = pixpos;
  294.  
  295.             r.left = pixpos;
  296.             r.right = pixpos+2*lcd->iTabW+1;
  297.  
  298.             InvalidateRect(hwnd, &r, TRUE);
  299.  
  300.             UpdateWindow(hwnd);
  301.  
  302.             // send notification message to parent window
  303.  
  304.             NMVLTABCHANGE nmvltc;
  305.  
  306.             nmvltc.hdr.code        = VLCN_TABCHANGE;
  307.             nmvltc.hdr.hwndFrom    = hwnd;
  308.             nmvltc.hdr.idFrom    = GetWindowLong(hwnd, GWL_ID);
  309.             nmvltc.iTab            = lcd->iMovingTab;
  310.             nmvltc.iNewPos        = pos;
  311.  
  312.             SendMessage(GetParent(hwnd), WM_NOTIFY, nmvltc.hdr.idFrom, (LPARAM)&nmvltc);
  313.         }
  314.         break;
  315.  
  316.     case VLCM_SETTABCOUNT:
  317.         lcd->nTabs = lParam;
  318.         if (wParam)
  319.             InvalidateRect(hwnd, &lcd->rTabBand, TRUE);
  320.         break;
  321.  
  322.     case VLCM_SETTABCOLOR:
  323.         lcd->rgbTab[LOWORD(wParam)] = lParam;
  324.         if (HIWORD(wParam))
  325.             InvalidateRect(hwnd, &lcd->rTabBand, TRUE);
  326.         break;
  327.  
  328.     case VLCM_MOVETABPOS:
  329.     case VLCM_SETTABPOS:
  330.         lcd->iPos[LOWORD(wParam)] = lParam;
  331.         lcd->iPixPos[LOWORD(wParam)] = LevelRatioToPixel(lParam, lcd->w);
  332.         if (HIWORD(wParam))
  333.             InvalidateRect(hwnd, &lcd->rTabBand, TRUE);
  334.  
  335.         if (msg == VLCM_MOVETABPOS) {
  336.             NMVLTABCHANGE nmvltc;
  337.  
  338.             nmvltc.hdr.code        = VLCN_TABCHANGE;
  339.             nmvltc.hdr.hwndFrom    = hwnd;
  340.             nmvltc.hdr.idFrom    = GetWindowLong(hwnd, GWL_ID);
  341.             nmvltc.iTab            = LOWORD(wParam);
  342.             nmvltc.iNewPos        = lParam;
  343.  
  344.             SendMessage(GetParent(hwnd), WM_NOTIFY, nmvltc.hdr.idFrom, (LPARAM)&nmvltc);
  345.         }
  346.         break;
  347.  
  348.     case VLCM_SETGRADIENT:
  349.         lcd->rgbLow = wParam;
  350.         lcd->rgbHigh = lParam;
  351.         InvalidateRect(hwnd, &lcd->rColorBand, FALSE);
  352.         break;
  353.  
  354.     default:
  355.         return DefWindowProc(hwnd, msg, wParam, lParam);
  356.     }
  357.     return FALSE;
  358. }
  359.